﻿using OcmKeep.entity;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OcmKeep
{
    public partial class OptionForm : Form
    {
        int TOTALNUM = 50;    //接受数据长度
        const int DEVNUM = 10;
        private string[] devh = new string[DEVNUM];
        byte[] devno = new byte[DEVNUM];
        bool canMove = false;
        Point mouseOff;
        Color HeaderBack = Color.FromArgb(50, 50, 50);
        Color ForeColor = Color.FromArgb(160, 160, 160);
        Color recvNor = Color.FromArgb(50, 50, 50);
        Color recvErr = Color.FromArgb(234, 32, 0);
        List<BrackeMachine> bm_Dev = new List<BrackeMachine>();
        SerialPort sp;
        DataHelper dh = new DataHelper();
        Stopwatch DelaySw = new Stopwatch();
        List<int> machinesList = new List<int>();
        List<Control> machineUnit = new List<Control>();
        List<Color> colorCir = new List<Color>(12);
        Control CurMachine;
        int PassWay = 2;//通道数
        public bool Face
        {
            set {
                cbFace.Checked = value;
                faceset();
            }
        }
        public List<PictureBox> facePreview;

        public string COM { set; get; }
        public bool LogState
        {
            set { cbLog.Checked = value; }
            get { return cbLog.Checked; }
        }
        public int SendSpace
        {
            set { sendSpace.Text = value.ToString(); }
            get
            {
                try
                {
                    return int.Parse(sendSpace.Text);
                }
                catch
                {
                    return 20;
                }
            }
        }

        public SerialPort SerPort { set; get; }

        public event EventHandler LogStateChanged;
        public event EventHandler SendSpaceChanged;
        public event EventHandler AllowTmpChanged;
        public event EventHandler AddrChanged;
        public event EventHandler PswChanged;
        IniHelper ini;
        public int[] inaddr;
        public int[] outaddr;
        bool isFirst = true;
        public OptionForm()
        {
            InitializeComponent();
            this.Load += OptionForm_Load;
            optionRight.AutoScrollPosition = new Point(0, 0);
        }


        void OptionForm_Load(object sender, EventArgs e)
        {
            init();
            CheckForIllegalCrossThreadCalls = false;
        }

        private void init(){
            
            header.MouseDown += Form1_MouseDown;
            header.MouseUp += Form1_MouseUp;
            header.MouseMove += Form1_MouseMove;
            close.MouseEnter += close_MouseEnter;
            close.MouseLeave += close_MouseLeave;
            string Current= Directory.GetCurrentDirectory();//获取当前根目录
            // 写入ini
            ini=new IniHelper(Current+"/Config/config.ini");
            string _logflag = ini.ReadValue("Setting", "logflag");
            cbLog.Checked = _logflag == "1" ? true : false;
            string _sendspace = ini.ReadValue("Setting", "sendspace");
            sendSpace.Text = _sendspace;
            string _passway = ini.ReadValue("Setting", "passway");//通道数
            if (_passway == null || _passway.CompareTo("0") <= 0) _passway = "2";
            int _intpassway = 2;
            int.TryParse(_passway, out _intpassway);
            cbPass.SelectedIndex = _intpassway - 1;
            PassWay = _intpassway;
            string InMachineAddr = ini.ReadValue("Setting", "inaddr");
            string OutMachineAddr = ini.ReadValue("Setting", "outaddr");
            string autorun = ini.ReadValue("Setting", "autorun");
            if (autorun == null || string.IsNullOrEmpty(autorun))
            {
                ini.WriteValue("Setting", "autorun", "1");
                autorun = "1";
            }
            cbAutoRun.Checked = autorun.Equals("1")?true:false;
            this.cbPass.SelectedIndexChanged += new System.EventHandler(this.cbPass_SelectedIndexChanged);
            colorCir.Add(Color.FromArgb(255,0,0));
            colorCir.Add(Color.FromArgb(255, 128, 0));
            //colorCir.Add(Color.FromArgb(255, 255, 0));
            colorCir.Add(Color.FromArgb(128, 255, 0));
            colorCir.Add( Color.FromArgb(0, 255, 0));
            colorCir.Add(Color.FromArgb(0, 255, 128));
            colorCir.Add(Color.FromArgb(0, 255, 255));
            colorCir.Add(Color.FromArgb(0, 128, 255));
            colorCir.Add(Color.FromArgb(0, 0, 255));
            colorCir.Add(Color.FromArgb(128, 0, 255));
            colorCir.Add(Color.FromArgb(255, 0, 255));
            colorCir.Add(Color.FromArgb(255, 0, 128));
        }

        void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && canMove)
            {
                Point mouseSet = Control.MousePosition;
                mouseSet.Offset(mouseOff.X, mouseOff.Y);  //设置移动后的位置  
                Location = mouseSet;
            }
        }

        void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                canMove = false;
            }
        }

        void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                mouseOff = new Point(-e.X, -e.Y);
                canMove = true;
            }
        }

        void close_MouseLeave(object sender, EventArgs e)
        {
            close.Image = Properties.Resources.close;
        }

        void close_MouseEnter(object sender, EventArgs e)
        {
            close.Image = Properties.Resources.close_f;
        }

        private void close_Click(object sender, EventArgs e)
        {
            try
            {
                if (sp.IsOpen) sp.Close();
            }
            catch { }
            this.Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void InitAutoRun()
        {
            string Current = AppDomain.CurrentDomain.BaseDirectory;
            bool ret = false;
            if (cbAutoRun.Checked)
            {
                ret = AutoRun.runWhenStart(true, "闸机控制", Current + "闸机控制.exe");
                if (ret) ini.WriteValue("Setting", "autorun", "1");
            }
            else
            {
                ret = AutoRun.runWhenStart(false, "闸机控制", Current + "闸机控制.exe");
                if (ret) ini.WriteValue("Setting", "autorun", "0");
            }
        }

        private void cbAutoRun_CheckedChanged(object sender, EventArgs e)
        {
            InitAutoRun();
        }

        private void cbLog_CheckedChanged(object sender, EventArgs e)
        {
            LogStateChanged(this, e);
            ini.WriteValue("Setting", "logflag", cbLog.Checked?"1":"0");
        }

        private void sendSpace_TextChanged(object sender, EventArgs e)
        {
            string _val = sendSpace.Text.Trim();
            if (_val.Length == 0) return;
            if (int.Parse(_val) > 1000)
            {
                sendSpace.Text = "1000";
                toolTip.Show("最大间隔为1000ms",sendSpace,500);
            }

            if (_val.Length>0&&int.Parse(_val) < 10)
            {
                sendSpace.Text = "10";
                toolTip.Show("最小间隔为10ms", sendSpace, 500);
            }
            if (_val.Substring(0, 1) == "0") {
                sendSpace.Text = _val.Substring(1);
            }
            try
            {
                SendSpaceChanged(this, e);
                ini.WriteValue("Setting", "sendspace", sendSpace.Text);
            }
            catch { 
                toolTip.Show("参数错误", sendSpace, 500);
            }
        }

        private void cbPass_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (DialogResult.Yes == MessageBox.Show("该配置生效需要重新启动程序", "", MessageBoxButtons.YesNo))
            {
                ini.WriteValue("Setting", "passway", (cbPass.SelectedIndex+1).ToString());
                Form1 main = this.Tag as Form1;
                if(main!=null)
                    main.closeForm();
                Application.Restart();
            }
            else {
                return;
            }
        }

        private void option1_Click(object sender, EventArgs e)
        {

            ThreadPool.QueueUserWorkItem(scrollAnim, 0);
        }

        private void option2_Click(object sender, EventArgs e)
        {
            ThreadPool.QueueUserWorkItem(scrollAnim,121);
        }

        private void scrollAnim(object pos) {
            int postion = (int)pos;
            int nowposition = optionRight.VerticalScroll.Value;
            int step = postion - nowposition>0?1:-1;
            while (optionRight.VerticalScroll.Value != postion)
            {
                optionRight.VerticalScroll.Value += step;
                //Thread.Sleep(1);
            }
        }

        private void scanMachines_Click(object sender, EventArgs e)
        {
            if (!sp.IsOpen)
            {
                MessageBox.Show("请先打开串口");
                return;
            }
            try
            {
                scanMachines.Text = "扫描中...";
                scanMachines.Enabled = false;
                ThreadPool.QueueUserWorkItem(sacenMachines,null);
                
            }catch(Exception ex){
                scanMachines.Text = "扫描闸机";
                scanMachines.Enabled = true;
                MessageBox.Show(ex.Message);
            }
        }
        
         private void sacenMachines(object state) {
             //dealData(null); return;
             for (int i = 0; i < inaddr.Length; i++) {
                 AddMahince(inaddr[i]);
             }
             for (int i = 0; i < outaddr.Length; i++)
             {
                 AddMahince(outaddr[i]);
             }
             concTest.Enabled = true;
            scanMachines.Text = "扫描闸机";
            recvTestbtn.Enabled= true;
             return;
        }

        private void dealData(object dt) {
            byte[] data = (byte[])dt;
            if (!dh.ValidSum(data))
            {
                return;
            }
            byte[] ack = dh.GetACK(data);
            int addr = dh.GetAddr(data);
            string addrStr = addr.ToString();
            bool insertFlag = true;
            for (int i = 0, len = machinesList.Count; i < len; ++i)
            {
                if (machinesList[i] == addr) insertFlag = false;
            } 
            if (insertFlag)
            {
                AddMahince(addr);   
            }
        }

        private string analyData(object dt) {
            byte[] data = (byte[])dt;
            if (!dh.ValidSum(data))
            {
                return "校验失败";
            }
            return BitConverter.ToString(data);
        }

        Color select = Color.FromArgb(200, 200, 200);
        void l_Click(object sender, EventArgs e)
        {
            Label cur = ((Label)sender);
            if (cur.BackColor != select)
            {
                if (CurMachine != null) {
                    CurMachine.BackColor = (Color)CurMachine.Tag;
                    CurMachine = null;
                }
                cur.BackColor = select;
                CurMachine = cur;
            }
            else {
                cur.BackColor = (Color)cur.Tag;
            }
        }

        private void AddMahince(int addr) {
            try
            {
                Random rd = new Random();
                Panel pb = new Panel();
                Label l = new Label();
                pb.Width = pb.Height = l.Width = 30;
                l.Dock = DockStyle.Fill;
                l.Click += l_Click;
                int clrInt = machinesList.Count;
                Console.WriteLine(machinesList.Count);
                pb.Location = clrInt >= DEVNUM / 2 ? new Point((clrInt - DEVNUM / 2) * 35 + 5, 40) : new Point((clrInt * 35) + 5, 5);
                l.BackColor = colorCir[clrInt];
                l.Tag = l.BackColor;
                l.TextAlign = ContentAlignment.MiddleCenter;
                l.ForeColor = Color.White;
                l.Text = (addr).ToString();
                pb.Controls.Add(l);
                AddMachinceContr(pb);
                machineUnit.Add(l);
                machinesList.Add(addr);
            }catch(Exception e){
            }

        }

        private void AddMachinceContr(Control pb)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(delegate { AddMachinceContr(pb); }));
                return;
            }
            machinesBox.Controls.Add(pb);
        }

        private void concTest_Click(object sender, EventArgs e)
        {
            int packlen = 0;
            if (!sp.IsOpen)
            {
                MessageBox.Show("请先打开串口");
                return;
            }
            else
            {
                if (CurMachine == null)
                {
                    MessageBox.Show("请选择要连接的闸机");
                    return;
                }
                else
                {
                    byte[] package= dh.GetPackage(int.Parse(CurMachine.Text), "", DataHelper.CMD.CMD_ERROR, ref packlen);
                    sp.Write(package, 0, packlen);
                }
            }

        }

        private void openCom_Click(object sender, EventArgs e)
        {
            try
            {
                if (SerPort != null && SerPort.IsOpen)
                {
                    SerPort.Close();
                }
                if (sp != null && sp.IsOpen)
                {
                    sp.Close();
                    if (!sp.IsOpen)
                    {
                        openCom.Text = "打开串口";
                        scanMachines.Enabled = concTest.Enabled = false;
                    }
                }
                else
                {
                    if (sp == null)
                    {
                        if (COM.Length <= 0)
                        {
                            MessageBox.Show("请在先启动页面选择串口", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                            return;
                        }
                        sp = new SerialPort();
                        sp.BaudRate = 115200;
                        sp.PortName = COM;
                        sp.Parity = Parity.Mark;
                    }
                    sp.Open();
                    if (sp.IsOpen)
                    {
                        openCom.Text = "关闭串口";
                        ThreadPool.QueueUserWorkItem(sacenMachines, null);
                    }
                }
            }
            catch(Exception ex) {
                MessageBox.Show(ex.Message, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

        }

        private void recvThread(object state) {
            int packlen = 0;
            int recvNum = 0;
            byte[] _devRev = new byte[TOTALNUM];
            if (!sp.IsOpen)
            {
                MessageBox.Show("请先打开串口");
                return;
            }
            else
            {
                if (CurMachine == null)
                {
                    MessageBox.Show("请选择要连接的闸机");
                    return;
                }
                else
                {
                    byte[] package = dh.GetPackage(int.Parse(CurMachine.Text), "", DataHelper.CMD.CMD_CARD, ref packlen);
                    sp.Write(package, 0, packlen);
                    sp.ReadTimeout = 50;
                    DelaySw.Restart();
                    try
                    {
                        do
                        {
                            int n = sp.BytesToRead;
                            if (n > 0)
                            {
                                recvNum += sp.Read(_devRev, recvNum, n > 31 ? 31 : n);//串口读
                            }

                        } while (recvNum != 11 && recvNum != 31 && DelaySw.ElapsedMilliseconds < 50);
                    }
                    catch (Exception e) {
                        recvTb.Text = "没有收到返回信息";
                        recvTb.ForeColor = recvErr;
                    }
                }
            }
            if (recvNum > 0)
            {
                recvTb.Text = analyData(_devRev);
                recvTb.ForeColor = recvNor;
            }
            else
            {
                recvTb.Text = "没有收到返回信息";
                recvTb.ForeColor = recvErr;
            }
        }

        private void recvTestbtn_Click(object sender, EventArgs e)
        {
            recvThread(null);
        }

        private void btnTestFinger_Click(object sender, EventArgs e)
        {
            if (CurMachine == null)
            {
                MessageBox.Show("请选择要连接的闸机");
                return;
            }
            string fingertmp = "03015F150000FFFEFFFEFFFEFFFEF006E002E000E000E000E000E000E000F000F000F002F802FC06000000000000000000000000000000004A21433E712BAAFE313684FE3CA8843F4AABDA9F4031DB5F62B2579F47B482FF3DBB843F68BDAC9F29AD05FC26301D5C56B0413D56BD40DD584041BD2F9BC6BA5833C07A6F352B1A2D9E5DFB6FBA2A366FB85611000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003014F2E0000E000C000C000C000C000C000C000C000C000C000C000C000C002E002E002F006F80E00000000000000000000000000000000322ED9FE6A32535E1A10DC3F3B921E9F3022C2DF7125531F7229937F232B439F4DAE2B9F41B2007F4DB396FF4136ACBF6B3FD2B763C394FF631892DD2C361A3D32B7C1DD453FAC9D48C2407D3C0AA17B380B089B779121D25F116598778E4C5359B66A595CB854D95C3B2A194E084B56568B0BD6718CA4764D935A16651491F65D8EE4576B118D71638461CE5C0BE0F4480DE1F46C8F4D8E6A15E2D46604CDCF7010A3555F0AE3B3551061F35F0761B16F148F915385A12B00000000000000000000000000000000";
            int len = 0;
            byte[] pack = dh.GetPackage(int.Parse(CurMachine.Text), fingertmp, DataHelper.CMD.CMD_FINGER, ref len);
            sp.Write(pack, 0, len);
        }


        private void faceset() {
            btnPreview.Visible=preview.Visible = cbFace.Checked;
        }

        private void btnPreview_Click(object sender, EventArgs e)
        {
            if (facePreview == null) {
                MessageBox.Show("获取摄像头失败","",MessageBoxButtons.OK,MessageBoxIcon.Error);
            }
            FormPreview pf = new FormPreview();
            pf.ShowDialog();
        }
        private void AllowTMP(bool isAllow) {
            if (CurMachine == null)
            {
                MessageBox.Show("请选择要连接的闸机");
                return;
            }
            if (!sp.IsOpen)
            {
                MessageBox.Show("串口被关闭");
                return;
            }
            int len = 0;
            byte[] pack;
            if (isAllow)
                pack = dh.GetPackage(int.Parse(CurMachine.Text), "", DataHelper.CMD.CMD_ALLOW, ref len);
            else 
                pack = dh.GetPackage(int.Parse(CurMachine.Text), "", DataHelper.CMD.CMD_DENY, ref len);
            sp.Write(pack, 0, len);
        }

        private void btnLoadPass_Click(object sender, EventArgs e)
        {
            if (CurMachine == null)
            {
                MessageBox.Show("请选择要连接的闸机");
                return;
            }
            if (tbPassWord.Text.Length > 0)
            {
                int len = 0;
                byte[] psw = DataTrans.ConvertIntToByteArray(long.Parse(tbPassWord.Text));
                string pswStr = BitConverter.ToString(psw).Replace("-", "");
                byte[] pack = dh.GetPackage(int.Parse(CurMachine.Text), pswStr, DataHelper.CMD.CMD_PSW, ref len);
                sp.Write(pack, 0, len);
            }
            else
            {
                MessageBox.Show("密码不能为空", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }
        private void btnChangeAddr_Click(object sender, EventArgs e)
        {
            int len = 0;
            if (CurMachine == null)
            {
                MessageBox.Show("请选择要连接的闸机");
                return;
            }
            if (tbAddr.Text.Length > 0)
            {
                if (IsInt(tbAddr.Text))
                {
                    string addr = tbAddr.Text;
                    int inAddr = int.Parse(addr);
                    if (inAddr > 8 || inAddr < 0) {
                        MessageBox.Show("地址只能填1-8");
                        return;
                    }
                    while(addr.Length!=4)addr ="0"+addr;
                    byte[] pack = dh.GetPackage(int.Parse(CurMachine.Text), addr, DataHelper.CMD.CMD_ADDR, ref len);
                    Console.WriteLine(BitConverter.ToString(pack));
                    sp.Write(pack, 0, len);
                }
                else
                {
                    MessageBox.Show("地址只能为数字", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("地址不能为空", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public static bool IsInt(string value)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(value, @"^\d*$");
        }
        private void btnAdv_Click(object sender, EventArgs e)
        {
            QuesDialog dialog = new QuesDialog();
            dialog.DialogRes += new EventHandler(
                (res, e1) =>
                {
                    if ((bool)res)
                    {
                        gpAdv.Visible = true;
                        gpAdv.Location = new Point(gpAdv.Location.X, btnAdv.Location.Y + 30);
                    }
                    else {
                        MessageBox.Show("密码错误", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            );
            dialog.ShowDialog();
        }

        private void btnAllow_Click(object sender, EventArgs e)
        {
            AllowTMP(true);
        }

        private void btnDeny_Click(object sender, EventArgs e)
        {
            AllowTMP(false);
        }

        private void cbFace_CheckedChanged(object sender, EventArgs e)
        {
            if (isFirst) {
                isFirst = false;
                return;
            }
            if (DialogResult.Yes == MessageBox.Show("该配置生效需要重新启动程序", "", MessageBoxButtons.YesNo))
            {
                ini.WriteValue("Setting", "face", cbFace.Checked ? "1" : "0");
                Application.Restart();
            }
            else
            {
                return;
            }
        }


    }
}
